from time import sleep

import tkinter as tk

from tkinter import Label

import cv2

from PIL import Image, ImageTk

import RPi.GPIO as GPIO

import time

 

# 使用BCM编号方式

GPIO.setmode(GPIO.BCM)

GPIO.setwarnings(False)

 

# 设置小车控制的GPIO端口1-4（根据BCM编号方式）

car_gpio_pins = [11,12 ,13, 15]

 

# 设置云台舵机的GPIO端口

servo_pins = [23, 24]

 

# 初始化舵机角度

servo_angles = {servo_pins[0]: 90, servo_pins[1]: 90}

 

def show_name(func):

   def wrapper(*args, **kwargs):

       print(f"Function '{func.__name__}' is called")

       return func(*args, **kwargs)

   return wrapper

 

@show_name

def init_car():

   # 将小车控制的GPIO端口设置为输出模式

   for pin in car_gpio_pins:

       GPIO.setup(pin, GPIO.OUT)

 

@show_name

def stop():

   for pin in car_gpio_pins:

       GPIO.output(pin, GPIO.LOW)

 

 

@show_name

def turn_left():

   stop()

   GPIO.output(car_gpio_pins[0], GPIO.HIGH)

   GPIO.output(car_gpio_pins[3], GPIO.HIGH)

 

@show_name

def turn_right():

   stop()

   GPIO.output(car_gpio_pins[1], GPIO.HIGH)

   GPIO.output(car_gpio_pins[2], GPIO.HIGH)

 

@show_name

def forward():

   stop()

   GPIO.output(car_gpio_pins[0], GPIO.HIGH)

   GPIO.output(car_gpio_pins[2], GPIO.HIGH)

 

 

@show_name

def backward():

   stop()

   GPIO.output(car_gpio_pins[1], GPIO.HIGH)

   GPIO.output(car_gpio_pins[3], GPIO.HIGH)

 

@show_name

def set_servo_angle(servo, angle):

   GPIO.setup(servo, GPIO.OUT)

   pwm = GPIO.PWM(servo, 50)

   pwm.start(8)

   duty_cycle = angle / 18. + 3.

   pwm.ChangeDutyCycle(duty_cycle)

   sleep(0.3)

   pwm.stop()

 

def adjust_servo_angle(servo, delta):

   new_angle = servo_angles[servo] + delta

   new_angle = max(0, min(180, new_angle))

   servo_angles[servo] = new_angle

   set_servo_angle(servo, new_angle)

 

 

def create_gui():

   root = tk.Tk()

   root.title("Car Control")

 

   # 创建视频显示标签

   video_label = Label(root)

   video_label.grid(row=0, column=0, columnspan=4)

 

   # 初始化摄像头

   cap = cv2.VideoCapture(0)

 

   def update_frame():

       ret, frame = cap.read()

       if ret:

           frame = cv2.flip(frame, -1)

           frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

           img = Image.fromarray(frame)

           imgtk = ImageTk.PhotoImage(image=img)

           video_label.imgtk = imgtk

           video_label.configure(image=imgtk)

       video_label.after(10, update_frame)

 

   update_frame()

 

   forward_button = tk.Button(root, text="Forward")

   forward_button.grid(row=1, column=1)

   forward_button.bind('<ButtonPress-1>', lambda event: forward())

   forward_button.bind('<ButtonRelease-1>', lambda event: stop())

 

   left_button = tk.Button(root, text="Left")

   left_button.grid(row=2, column=0)

   left_button.bind('<ButtonPress-1>', lambda event: turn_left())

   left_button.bind('<ButtonRelease-1>', lambda event: stop())

 

   stop_button = tk.Button(root, text="Stop")

   stop_button.grid(row=2, column=1)

   stop_button.bind('<ButtonPress-1>', lambda event: stop())

 

   right_button = tk.Button(root, text="Right")

   right_button.grid(row=2, column=2)

   right_button.bind('<ButtonPress-1>', lambda event: turn_right())

   right_button.bind('<ButtonRelease-1>', lambda event: stop())

 

   backward_button = tk.Button(root, text="Backward")

   backward_button.grid(row=3, column=1)

   backward_button.bind('<ButtonPress-1>', lambda event: backward())

   backward_button.bind('<ButtonRelease-1>', lambda event: stop())

 

  # 云台控制按钮

   servo_up_button = tk.Button(root, text="Servo Up")

   servo_up_button.grid(row=1, column=3)

   servo_up_button.bind('<ButtonPress-1>', lambda event: adjust_servo_angle(servo_pins[1], -5))

 

   servo_down_button = tk.Button(root, text="Servo Down")

   servo_down_button.grid(row=3, column=3)

   servo_down_button.bind('<ButtonPress-1>', lambda event: adjust_servo_angle(servo_pins[1], 5))

 

   servo_left_button = tk.Button(root, text="Servo Left")

   servo_left_button.grid(row=2, column=3)

   servo_left_button.bind('<ButtonPress-1>', lambda event: adjust_servo_angle(servo_pins[0], -5))

 

   servo_right_button = tk.Button(root, text="Servo Right")

   servo_right_button.grid(row=2, column=4)

   servo_right_button.bind('<ButtonPress-1>', lambda event: adjust_servo_angle(servo_pins[0], 5))

 

   root.mainloop()

   cap.release()

 

if __name__ == "__main__":

   init_car()

   create_gui()

   GPIO.cleanup()